<template>
  <div>
    <el-card>
      <h1 style="width: 20%; margin: auto">算法介绍</h1>
      <p style="font-size: large">
        关联规则分析（Association Rule Mining）是一种从大规模数据集中发现变量间潜在关联性的算法，典型应用如“购物篮分析”。其核心目标是找到形如 “如果A发生，则B也可能发生” 的规则（即 A ⇒ B A⇒B），并通过统计指标量化关联强度。通过合理选择算法、优化参数配置，关联规则分析能有效挖掘数据价值，驱动业务决策。实际应用中需结合领域知识验证规则合理性，避免过度依赖统计显著性
      </p>
      <el-table
        :data="tableData"
        style="width: 100%">
        <el-table-column
          prop="name"
          label="算法分析指标"
          width="180">
        </el-table-column>
        <el-table-column
          prop="mean"
          label="定义"
          width="180">
        </el-table-column>
        <el-table-column
          prop="count"
          label="算式">
        </el-table-column>
        <el-table-column
          prop="earn"
          label="意义">
        </el-table-column>
      </el-table>
    </el-card>

    <el-card>
      <h1 style="width: 20%; margin: auto">数据集选择</h1>
      <el-select v-model="courseSelect" filterable placeholder="请选择课程" style="width: 10%; margin: 1%">
        <el-option
          v-for="item in courseOptions"
          :key="item.subId"
          :label="item.subName"
          :value="item.subId">
        </el-option>
      </el-select>
      <el-select v-model="classSelect" filterable placeholder="请选择班级" style="width: 10%; margin: 1%">
        <el-option
          v-for="item in classOptions"
          :key="item.classId"
          :label="item.className"
          :value="item.classId">
        </el-option>
      </el-select>
      <el-input v-model="scoreCut" placeholder="请输入课程高分与低分区分值(0-100)" @input="handleInput" @blur="handleBlur" style="width: 26%; margin: 1%">
        <template #prepend>
          <p style="height: 10px">课程成绩:</p>
        </template>
      </el-input>
      <el-input v-model="evaScoreCut" placeholder="请输入评教高分与低分区分值(0-100)" @input="handleInput2" @blur="handleBlur2" style="width: 26%; margin: 1%">
        <template #prepend>
          <p style="height: 10px">学生评教:</p>
        </template>
      </el-input>
      <el-button type="primary" @click="ruleAnalyse" style="width: 8%; margin: 1%">开始分析</el-button>
    </el-card>

    <div v-if="show">
      <el-card>
        <h1 style="width: 20%; margin: auto">分析图表</h1>
        <div class="chart-container">
          <!-- 支持度-置信度散点图 -->
          <div id="scatterChart" class="chart-box"></div>
        </div>
      </el-card>

      <el-card>
        <h1 style="width: 20%; margin: auto">分析结果说明</h1>
        <el-table
          :data="valuesTable"
          style="width: 100%"
        >
          <el-table-column
            prop="rule"
            label="关联规则"
            style="width: 25%; margin: auto"
          />
          <el-table-column
            prop="support"
            label="支持度"
            style="width: 25%; margin: auto"
          />
          <el-table-column
            prop="confidence"
            label="置信度"
            style="width: 25%; margin: auto"
          />
          <el-table-column
            prop="lift"
            label="提升度"
            sortable
            style="width: 25%; margin: auto"
          />
        </el-table>
      </el-card>

      <div class="chart-container" v-if="false">
        <!-- 规则指标表格 -->
        <div id="tableChart" class="chart-box"></div>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import axios from 'axios'

export default {
  data() {
    return {
      scoreCut: '',
      evaScoreCut: '',
      thisData: [],
      thisLink: [],
      courseData: [],
      courseOptions: [],
      classOptions: [],
      courseSelect: '',
      classSelect: '',
      show: false,
      items: [],
      rules: [],
      valuesTable: [],
      tableData: [
        {
          name: '支持度',
          mean: '支持度表示某个项集在所有样本中出现的频率。',
          count: 'Support(X→Y) = 同时包含 X 和 Y 的样本数 / 总样本数 = ∣X∩Y∣ / N',
          earn: '支持度越高，说明该规则覆盖的样本呢越多，越可能具有某种价值。'
        },
        {
          name: '置信度',
          mean: '置信度表示在包含 X 的样本中，同时包含 Y 的比例',
          count: 'Confidence(X→Y) = 同时包含 X 和 Y 的样本数 / 包含X的样本数 = ∣X∩Y∣ / ∣X∣',
          earn: '置信度越高，规则越可靠'
        },
        {
          name: '提升度',
          mean: '提升度表示规则的有效性，即前件 X 的出现对后件 Y 出现概率的提升程度',
          count: 'Lift(X→Y) = Confidence(X→Y) / Support(Y) = ∣X∩Y∣/∣X∣ / ∣Y∣/N',
          earn: 'Lift > 1：规则有效（X 的出现提升了 Y 的概率）。\n' +
            'Lift = 1：随机关联（无实际意义）。\n' +
            'Lift < 1：负相关（X 的出现降低了 Y 的概率）'

        }
      ]
    }
  },
  mounted() {
    this.getClassOptions()
    this.getCourseOptions()
  },
  methods: {
    handleInput(value) {
      const filtered = value.replace(/[^\d]/g, '') // 移除非数字字符
      this.scoreCut = filtered ? parseInt(filtered, 10) : 0
    },
    handleBlur() {
      if (this.scoreCut < 0) this.scoreCut = 0
      else if (this.scoreCut > 100) this.scoreCut = 100
    },
    handleInput2(value) {
      const filtered = value.replace(/[^\d]/g, '') // 移除非数字字符
      this.evaScoreCut = filtered ? parseInt(filtered, 10) : 0
    },
    handleBlur2() {
      if (this.evaScoreCut < 0) this.evaScoreCut = 0
      else if (this.evaScoreCut > 100) this.evaScoreCut = 100
    },
    async getCourseOptions() {
      await axios.get('http://localhost:8080/course/get_all').then((res) => {
        for (let i = 0; i < res.data.data.length; i++) {
          this.courseOptions[i] = {
            subName: '',
            subId: ''
          }
          this.courseOptions[i].subName = res.data.data[i].subName
          this.courseOptions[i].subId = res.data.data[i].subId
        }
        this.courseOptions[this.courseOptions.length - 1].subName = 'ALL'
        this.courseOptions[this.courseOptions.length - 1].subId = 'ALL'
        this.courseSelect = '请选择课程'
      })
    },
    async getClassOptions() {
      await axios.get('http://localhost:8080/class/get_all').then((res) => {
        for (let i = 0; i < res.data.data.length; i++) {
          this.classOptions[i] = {
            className: '',
            classId: ''
          }
          this.classOptions[i].className = res.data.data[i].className
          this.classOptions[i].classId = res.data.data[i].classId
        }
        this.classOptions[this.classOptions.length - 1].className = 'ALL'
        this.classOptions[this.classOptions.length - 1].classId = 'ALL'
        this.classSelect = '请选择班级'
      })
    },
    async rulesGet() {
      if (this.courseSelect === '请选择课程' || this.courseSelect === 'ALL') {
        this.courseSelect = null
      }
      if (this.classSelect === '请选择班级' || this.classSelect === 'ALL') {
        this.classSelect = null
      }

      const params = new URLSearchParams()
      params.append('classId', this.classSelect)
      params.append('subId', this.courseSelect)
      params.append('scoreCut', this.scoreCut)
      params.append('evaScoreCut', this.evaScoreCut)

      await axios.post('http://localhost:8080/association/association_details_rules', params, {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded' // 必须指定 Content-Type
        }
      }).then((res) => {
        console.log(res)
        this.rules = res.data.data
        // 未查询到相关数据进行提示
        if (res.data.success === false) {
          this.$message.error('未查询到相关数据')
          return
        }
      })
    },
    async ruleAnalyse() {
      this.show = true
      await this.rulesGet()

      const valuesTable = []
      this.valuesTable = []
      valuesTable[0] = [
        '规则', '支持度', '置信度', '提升度'
      ]
      for (let i = 0; i < this.rules.length; i++) {
        valuesTable.push([
          this.rules[i].rule,
          this.rules[i].support + '%',
          this.rules[i].confidence + '%',
          this.rules[i].lift
        ])
      }

      const valuesGraph = []
      for (let i = 0; i < this.rules.length; i++) {
        valuesGraph.push([
          this.rules[i].support,
          this.rules[i].confidence,
          this.rules[i].rule
        ])

        this.valuesTable[i] = {
          rule: this.rules[i].rule,
          support: Number(this.rules[i].support).toFixed(2) + '%',
          confidence: Number(this.rules[i].confidence).toFixed(2) + '%',
          lift: Number(this.rules[i].lift).toFixed(2)
        }
      }

      // ======================
      // 3. 表格 - 规则指标展示
      // ======================
      const tableOption = {
        title: { text: '关联规则详情', left: 'center' },
        grid: { left: '5%', containLabel: true },
        xAxis: { show: false },
        yAxis: { type: 'category', inverse: true },
        series: [{
          type: 'custom',
          renderItem: (params, api) => {
            return {
              type: 'group',
              children: valuesTable.map((row, rowIndex) => ({
                type: 'text',
                style: {
                  text: row.join(' | '),
                  x: 50 + rowIndex * 0,
                  y: params.coordSys.y + rowIndex * 30,
                  fill: rowIndex === 0 ? '#5470C6' : '#666',
                  fontWeight: rowIndex === 0 ? 'bold' : 'normal'
                }
              }))
            }
          },
          data: [{}]
        }]
      }

      // ======================
      // 4. 散点图 - 支持度 vs 置信度
      // ======================
      const scatterOption = {
        title: { text: '支持度-置信度分布', left: 'center' },
        xAxis: { name: '支持度 (%)', min: 0, max: 100 },
        yAxis: { name: '置信度 (%)', min: 0, max: 100 },
        series: [{
          type: 'scatter',
          data: valuesGraph,
          symbolSize: (val) => val[2].length * 3,
          itemStyle: { color: '#91CC75' },
          label: {
            show: true,
            formatter: '{@[2]}',
            position: 'top'
          }
        }]
      }

      // ======================
      // 初始化所有图表
      // ======================
      const initChart = (domId, option) => {
        const chart = echarts.init(document.getElementById(domId))
        chart.setOption(option)
        window.addEventListener('resize', () => chart.resize())
      }

      // 初始化图表
      initChart('scatterChart', scatterOption)
      initChart('tableChart', tableOption)
    }
  }
}
</script>

<style>
.chart-container {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}
.chart-box {
  height: 800px;
  width: 800px;
  border: 1px solid #eee;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
</style>
